/* vim: set sw=4 ts=4 sts=4 expandtab: */
#include <e.h>
#include "config.h"
#include "e_mod_main.h"
#include "e_mod_oplist.h"

#define FREE_STR(str) \
   if (str) free(str); \
   str = NULL;

/* Registry callbacks */
static int _oplist_reg_add_cb(void *data, int type, void *event);
static void _oplist_reg_changed_cb(void *data, E_Fm2_Op_Registry_Entry *entry);
static Evas_Object *_oplist_entry_new(E_Fm2_Op_Registry_Entry *re);

static Ecore_Event_Handler *reg_add = NULL;
static char theme_file[PATH_MAX];
Eina_List *ops;

void oplist_init(void)
{
    ops = NULL;
    snprintf(theme_file, PATH_MAX, "%s/e-module-oplist.edj", oplist_conf->
                                                                module->dir);
    reg_add = ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_ADD,
                                                _oplist_reg_add_cb, NULL);
}

void oplist_shutdown(void)
{
    E_Fm2_Op_Registry_Entry *re;

    ecore_event_handler_del(reg_add);
    reg_add = NULL;

    EINA_LIST_FREE(ops, re)
        e_fm2_op_registry_entry_unref(re);
}

void oplist_update_all_gadgets(void)
{

}

void oplist_fill_box(Evas_Object *box)
{
    Eina_List *l;
    E_Fm2_Op_Registry_Entry *re;
    Evas_Object *o;

    EINA_LIST_FOREACH(ops, l, re)
    {
        if (!re)
            continue;

        o = _oplist_entry_new(re);
        evas_object_show(o);
        e_box_pack_end(box, o);
        e_box_pack_options_set(o, 1, 0, /* fill */
                                  1, 0, /* expand */
                                  0.5, 0.0, /* align */
                                  min_w, min_h, /* min */
                                  max_w, max_h /* max */
                                );
    }

}

void oplist_empty_box(Evas_Object *box)
{
    int count;
    Evas_Object *o;
    Evas_Object *swal;

    e_box_freeze(box);
    count = e_box_pack_count_get(box);
    
    while (count >= 0)
    {
        Evas_Object *o;
        Evas_Object *swal;

        o = e_box_pack_object_nth(box, count);
        swal = edje_object_part_swallow_get(o, "icon");

        if (swal)
        {
            edje_object_part_unswallow(o, swal);
            evas_object_del(swal);
        }

        e_box_unpack(o);
        evas_object_del(o);

        count--;
    }

    e_box_thaw(box);
}

static int _oplist_reg_add_cb(void *data __UNUSED__, int type, void *event)
{
    E_Fm2_Op_Registry_Entry *re;

    re = event;

    if (!re)
        return;

    /* Ref the entry so it'll stick around */
    e_fm2_op_registry_entry_ref(re);

    /* Add to our references list */
    ops = eina_list_prepend(ops, re);

    /* Add the other event handlers here */
    /* XXX Data here should be the evas object XXX */
    e_fm2_registry_entry_listener_add(re, _oplist_reg_changed_cb, NULL, NULL);

    /*
     * XXX Add to box here 
     */

    return ECORE_CALLBACK_RENEW;
}


static void _oplist_reg_changed_cb(void *data, E_Fm2_Op_Registry_Entry *entry)
{
    Evas_Object *item;

    item = data;
    if (!item)
        return;

    switch (entry->status)
    {
        case E_FM2_OP_STATUS_UNKNOWN:
            // XXX How to handle these?
            edje_object_signal_emit(item, "oplist/status/unknown", "oplist");
            break;

        case E_FM2_OP_STATUS_IN_PROGRESS:
            edje_object_signal_emit(item, "oplist/status/progress", "oplist");
            // XXX Send message
            edje_object_part_text_set(item, "item/status", D_("In Progress"));
            // XXX Set start time
            // XXX Set time remaining
            break;

        case E_FM2_OP_STATUS_SUCCESSFUL:
            if (oplist_conf->hist_len == 0)
            {
                e_fm2_op_registry_entry_listener_del(entry,
                                                _oplist_reg_changed_cb, data);
                e_fm2_op_registry_entry_unref(entry);
                ops = eina_list_remove(ops, entry);
            }
            else
            {
                // XXX Handle the proper history priorities here
            }
            break;

        case E_FM2_OP_STATUS_ABORTED:
            // XXX Send status message
            // XXX Set up timer to automatically remove?
            break;

        case E_FM2_OP_STATUS_ERROR:
            // XXX Send status message
            // XXX Leave these in until manually removed by user?
            break;

        default:
            break;
    }
}

static Evas_Object *
_oplist_entry_new(E_Fm2_Op_Registry_Entry *re)
{
    Evas_Object *o, *sep, *icon;
    char buf[PATH_MAX];
    int min_w, min_h, max_w, max_h;

    if (!re)
        continue;

    /* List object */
    o = edje_object_add(evas_object_evas_get(box));
    edje_object_file_set(o, theme_file, "modules/oplist/main");

    switch (re->op)
    {
        case E_FM_OP_COPY:
            snprintf(buf, sizeof(buf), D_("Copy from %s to %s"), re->src,
                                                                    re->dst);
            break;

        case E_FM_OP_MOVE:
            snprintf(buf, sizeof(buf), D_("Move from %s to %s"), re->src,
                                                                    re->dst);
            break;

        case E_FM_OP_REMOVE:
            snprintf(buf, sizeof(buf), D_("Remove from %s"), re->src);
            break;
    }

    edje_object_part_text_set(o, "operation_description", buf);
    
    if (!e_box_orientation_get(box))
        edje_object_signal_emit(o, "separator/set/horiz", "oplist");
    else
        edje_object_signal_emit(o, "separator/set/vert", "oplist");

    /* connect signals from edje */
    edje_object_signal_callback_add(o, "show_win", "oplist",
                                            _oplist_entry_show_win, re);
    edje_object_signal_callback_add(o, "cancelled", "oplist",
                                            _oplist_entry_cancelled, re);
}

void _oplist_entry_show_win(void *data, Evas_Object *o,
                                        const char *emission __UNUSED__,
                                        const char *source __UNUSED__)
{
    printf("entry show win\n");
}

void _oplist_entry_cancelled(void *data, Evas_Object *o,
                                        const char *emission __UNUSED__,
                                        const char *source __UNUSED__)
{
    printf("entry cancelled\n");
}

